package com.monochromebytes.mononet.virtual;

import java.nio.ByteBuffer;

import com.monochromebytes.mononet.packet.OutgoingPacket;

public class OutgoingDataPacket extends DataPacket {

    private final VirtualAddress connectionAddress;

    private final int             timeToLive;

    public OutgoingDataPacket(VirtualAddress address, SequenceNumber number, Acknowledgment acknowledgment, int length, int timeToLive) {
        super(new OutgoingPacket(DataPacket.HEADER_LENGTH + length, address.getLocalAddress(),
                address.getRemoteAddress()));

        // Set connection ID.
        ConnectionID packetConnectionID = this.getConnectionID();
        packetConnectionID.set(address.getConnectionID());

        // Set sequence number.
        SequenceNumber packetNumber = this.getSequenceNumber();
        packetNumber.set(number);

        // Set acknowledgement.
        Acknowledgment packetAcknowledgment = this.getAcknowledgment();
        packetAcknowledgment.set(acknowledgment);
        
        this.connectionAddress = address;
        this.timeToLive = timeToLive;
    }

    @Override
    public VirtualAddress getConnectionAddress() {
        return this.connectionAddress;
    }

    @Override
    public OutgoingPacket getUDPPacket() {
        return (OutgoingPacket) super.getUDPPacket();
    }

    public boolean isLost() {
        // Check if the packet is sent.
        OutgoingPacket udpPacket = this.getUDPPacket();
        if (!udpPacket.isSent()) {
            return false;
        }

        // Check if the packet has been lost.
        long timeOfDeath = udpPacket.getTimestampOfOutput() + this.timeToLive;
        long now = System.currentTimeMillis();
        if (now <= timeOfDeath) {
            return false;
        }

        return true;
    }

    public void putData(ByteBuffer data) {
        ByteBuffer packetData = this.getData();
        packetData.put(data);
    }
    
    public int getTimeToLive() {
        return this.timeToLive;
    }
    
    public long getTimestampOfOutput() {
        OutgoingPacket packet = getUDPPacket();
        return packet.getTimestampOfOutput();
    }
}
